package net.expectx.common.single.util;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;

import java.lang.reflect.Method;
import java.util.*;

/**
 * BeanUtil
 * @author jianhun
 * @date 2018/5/21
 */
public class BeanUtil {

    public static void bean2Bean(Object from, Object to, String[] excludsArray) throws Exception {
        List<String> excludesList = null;
        if(excludsArray != null && excludsArray.length > 0) {
            //构造列表对象
            excludesList = Arrays.asList(excludsArray);
        }
        Method[] fromMethods = from.getClass().getDeclaredMethods();
        Method[] toMethods = to.getClass().getDeclaredMethods();
        Method fromMethod = null, toMethod = null;
        String fromMethodName = null, toMethodName = null;
        for (int i = 0; i < fromMethods.length; i++) {
            fromMethod = fromMethods[i];
            fromMethodName = fromMethod.getName();
            if (!fromMethodName.contains("get")) {
                continue;
            }
            //排除列表检测
            if(excludesList != null && excludesList.contains(
                    StringUtil.toLowerCaseFirstOne(fromMethodName.substring(3)))) {
                continue;
            }
            toMethodName = "set" + fromMethodName.substring(3);
            toMethod = findMethodByName(toMethods, toMethodName);
            if (toMethod == null) {
                continue;
            }
            Object value = fromMethod.invoke(from, new Object[0]);
            if(value == null) {
                continue;
            }
            //集合类判空处理
            if(value instanceof Collection) {
                Collection<?> newValue = (Collection<?>)value;
                if(newValue.size() <= 0) {
                    continue;
                }
            }
            toMethod.invoke(to, new Object[] {value});
        }
    }

    private static Method findMethodByName(Method[] methods, String name) {
        for (int j = 0; j < methods.length; j++) {
            if (methods[j].getName().equals(name)) {
                return methods[j];
            }
        }
        return null;
    }

    public static <T>HashMap<String, Object> bean2HashMap(T t, String[] array, boolean isExclude) throws Exception {

        HashMap<String, Object> map = Maps.newHashMapWithExpectedSize(7);
        List<String> excludesList = null;
        if(array != null && array.length > 0) {
            // 构造列表对象
            excludesList = Arrays.asList(array);
        }
        Class<?> c = t.getClass();
        Method[] methods = c.getDeclaredMethods();
        if(methods.length > 0) {
            for(Method method : methods) {
                String methodName = method.getName();
                String key = StringUtil.toLowerCaseFirstOne(methodName.substring(3));
                if(!methodName.contains("get")) {
                    continue;
                }
                if(excludesList != null) {
                    boolean isExisted =
                            (isExclude && excludesList.contains(key)) || (!isExclude && !excludesList.contains(key));
                    if(isExisted) {
                        continue;
                    }
                }
                Object value = method.invoke(t);
                map.put(key, value);
            }
        }
        return map;
    }

    public static <T> String bean2Json(T t) throws Exception {

        return JSON.toJSONString(t);

    }

    public static <T> T json2bean(String json, Class<T> clazz) throws Exception {

        return JSON.parseObject(json, clazz);

    }

    public static Map<String, Object> json2Map(String json) throws Exception {

        return JSON.parseObject(json, Map.class);

    }

    public static <T> T map2bean(Map<?, ?> map, Class<T> clazz) throws Exception {

        return JSON.parseObject(JSON.toJSONString(map), clazz);

    }

 }
